<template>
  <el-dialog
    :title="dialogTitle"
    :visible.sync="dialogVisible"
    width="25%"
    :close-on-click-modal="false"
    :before-close="handleClose"
  >
    <div class="upload-web-container" @dragover="handleDrageOver">
      <div class="folder-path">
        <span>路径:</span>
        <el-link :underline="false">{{ getFolderPath }}</el-link>
      </div>
      <div class="upload-reminder"><span>温馨提示:</span> <span>上传目录只会把选择的目录下的文件上传到指定路径下面</span></div>
      <div class="folder-upload">
        <input
          v-show="false"
          id="uploadDirectory"
          type="file"
          webkitdirectory
          @change="uploadFolderChange"
          multiple
        />
        <div class="upload-title">选择目录:</div>
        <!-- 选择文件区域 -->
        <div
          id="uploadContainer"
          class="upload-container"
          :class="dragInput ? 'upload-container-hover' : ''"
          @click="clickSelectFolder"
          @dragenter="handleDragEnter"
          @drop="handleDrageDrop"
        >
          <div class="upload-icon">
            <svg-icon icon-class="upload-folder" :size="8"></svg-icon>
          </div>
          <div class="upload-remark">
            <span>将文件拖到此处，或</span>
            <span>点击上传</span>
          </div>
        </div>
      </div>
      <div class="file-title-container" v-if="uploadFormDatas.length > 0">
        <span>已选择</span>
        <span>{{ uploadFormDatas.length }}</span>
        <span>文件</span>
        <span>大小</span>
        <span>{{ getFileSize }}</span>
        <span><el-link @click="uploadFileDetail">详情</el-link></span>
      </div>

      <!-- 当前执行的上传文件信息 -->
      <div class="current-upload-container" v-if="currentUploadFile.file">
        <div>当前上传:</div>
        <div>
          <el-tooltip :content="currentUploadFile.name" placement="left-start">
            <span>{{ currentUploadFile.name }}</span>
          </el-tooltip>
        </div>
        <div>
          <span
            v-if="
              currentUploadFile.percentage === 0 &&
              currentUploadFile.upload === 0
            "
            >未开始</span
          >
          <span
            v-if="
              currentUploadFile.percentage > 0 && currentUploadFile.upload === 0
            "
            ><span style="color: #e6a23c; margin-right: 5px">准备中</span
            ><span style="color: #409eff">{{
              currentUploadFile.percentage + "%"
            }}</span></span
          >
          <span v-if="currentUploadFile.upload === 1" style="color: #67c23a"
            >执行中</span
          >
          <span v-if="currentUploadFile.upload === 2" style="color: #67c23a"
            >上传成功</span
          >
          <span v-if="currentUploadFile.upload === 3" style="color: #d81e06">
            <el-tooltip
              :content="'上传失败:' + currentUploadFile.errorMsg"
              placement="left-start"
            >
              <span
                >上传失败:<span
                  style="
                    font-weight: normal;
                    font-size: 15px;
                    margin-left: 10px;
                  "
                  >{{ currentUploadFile.errorMsg }}</span
                ></span
              >
            </el-tooltip>
          </span>
        </div>
      </div>
    </div>
    <span slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取 消</el-button>
      <el-button
        type="primary"
        :loading="
          loading &&
          (currentUploadFile.upload === 2 || currentUploadFile.upload === 3)
        "
        @click="handleConfirm"
        >上传
      </el-button>
    </span>

    <el-drawer
      :visible.sync="uploadDetailConfig.visible"
      direction="rtl"
      :append-to-body="true"
      :before-close="handleDetailClose"
      size="50%"
    >
      <div slot="title" class="drawer-detail-title">
        <div>文件上传详情</div>
        <div>当前上传:</div>
        <div>
          <el-tooltip :content="currentUploadFile.name" placement="left-start">
            <span>{{ currentUploadFile.name }}</span>
          </el-tooltip>
        </div>
        <div>
          {{
            currentUploadFile.size > 1024
              ? Math.round(currentUploadFile.size / 1024, 0) + "KB"
              : currentUploadFile.size + "B"
          }}
        </div>
        <div>
          <span
            v-if="
              currentUploadFile.percentage === 0 &&
              currentUploadFile.upload === 0
            "
            >未开始</span
          >
          <span
            v-if="
              currentUploadFile.percentage > 0 && currentUploadFile.upload === 0
            "
            ><span style="color: #e6a23c; margin-right: 5px">准备中</span
            ><span style="color: #409eff">{{
              currentUploadFile.percentage + "%"
            }}</span></span
          >
          <span v-if="currentUploadFile.upload === 1" style="color: #67c23a"
            >执行中</span
          >
          <span v-if="currentUploadFile.upload === 2" style="color: #67c23a"
            >上传成功</span
          >
          <span v-if="currentUploadFile.upload === 3" style="color: #d81e06">
            <el-tooltip
              :content="'上传失败:' + currentUploadFile.errorMsg"
              placement="left-start"
            >
              <span
                >上传失败:<span
                  style="
                    font-weight: normal;
                    font-size: 15px;
                    margin-left: 10px;
                  "
                  >{{ currentUploadFile.errorMsg }}</span
                ></span
              >
            </el-tooltip>
          </span>
        </div>
      </div>
      <div class="drawer-detail-container">
        <div class="column-header">
          <span>文件名</span>
          <span>大小</span>
          <span>缓存路径</span>
          <span>进度</span>
          <span>状态</span>
        </div>
        <div
          class="column-cell"
          v-for="(item, index) in uploadFormDatas"
          :key="index"
        >
          <div>{{ item.name }}</div>
          <div>
            {{
              item.size > 1024
                ? Math.round(item.size / 1024, 0) + "KB"
                : item.size + "B"
            }}
          </div>
          <div>{{ item.filePath }}</div>
          <div>
            <span v-if="item.percentage === 0 && item.upload === 0"
              >未开始</span
            >
            <span v-if="item.percentage > 0 && item.upload === 0"
              ><span style="color: #e6a23c; margin-right: 5px">准备中</span
              ><span style="color: #409eff">{{
                item.percentage + "%"
              }}</span></span
            >
            <span v-if="item.upload === 1" style="color: #67c23a">执行中</span>
            <span v-if="item.upload === 2" style="color: #67c23a"
              >上传成功</span
            >
            <span v-if="item.upload === 3" style="color: #d81e06">
              <el-tooltip
                :content="'上传失败:' + item.errorMsg"
                placement="left-start"
              >
                <span>上传失败:{{ item.errorMsg }}</span>
              </el-tooltip>
            </span>
          </div>
          <div>
            <svg-icon
              :class="item.upload === 1 ? 'upload-runing-svg-rotate' : ''"
              :icon-class="
                item.upload === 0
                  ? 'ready'
                  : item.upload === 1
                  ? 'setting'
                  : item.upload === 2
                  ? 'success'
                  : 'error'
              "
            ></svg-icon>
          </div>
        </div>
      </div>
    </el-drawer>
  </el-dialog>
</template>
<script>
import { uploadDir } from "@/api/linux/folder";

export default {
  name: "UploadDir",
  props: {
    title: {
      type: String,
      default: () => "",
    },
    visible: {
      type: Boolean,
      default: () => false,
    },
    folderPath: {
      type: String,
      default: () => "",
    },
  },
  computed: {
    dialogTitle: {
      get() {
        return this.title;
      },
    },
    dialogVisible: {
      get() {
        return this.visible;
      },
    },
    getFolderPath: {
      get() {
        return this.folderPath;
      },
    },
    getFileSize() {
      if (!this.uploadFormDatas || this.uploadFormDatas.length <= 0)
        return "0B";
      let uploadFileSize = 0;
      for (let i = 0; i < this.uploadFormDatas.length; i++) {
        uploadFileSize = uploadFileSize + this.uploadFormDatas[i].size;
      }
      if (uploadFileSize < 1024) {
        return uploadFileSize + "B";
      } else if (uploadFileSize > 1024 && uploadFileSize < 1024 * 1024) {
        return Math.round(uploadFileSize / 1024, 0) + "KB";
      }
      return Math.round(uploadFileSize / (1024 * 1024), 0) + "MB";
    },
  },
  data() {
    return {
      dragInput: false,
      uploadFormDatas: [],
      uploadDetailConfig: {
        visible: false,
      },
      currentUploadFile: {},
      loading: false,
    };
  },
  methods: {
    // 点击选择目录
    clickSelectFolder() {
      document.getElementById("uploadDirectory").click();
    },

    // 拖拽目录拖入事件
    handleDragEnter(event) {
      event.preventDefault();
      this.dragInput = true;
    },

    // 拖拽目录移动中监听事件
    handleDrageOver(event) {
      event.preventDefault();
      if (!this.dialogVisible) return;
      const dirCurrentX = event.clientX;
      const dirCurrentY = event.clientY;
      const uploadContainerNode = document.getElementById("uploadContainer");
      // 获取元素的位置和大小
      const rect = uploadContainerNode.getBoundingClientRect();
      // 判断鼠标是否在元素区域内
      const isInside =
        dirCurrentX >= rect.left &&
        dirCurrentX <= rect.right &&
        dirCurrentY >= rect.top &&
        dirCurrentY <= rect.bottom;
      this.dragInput = isInside;
    },

    // 拖拽目录拖放事件
    handleDrageDrop(event) {
      this.dragInput = false;
      event.preventDefault();
      const items = event.dataTransfer.items;
      for (let i = 0; i < items.length; i++) {
        // 使用webkitGetAsEntry获取Entry对象
        const item = items[i].webkitGetAsEntry();
        this.handleDropDirOrFile(item, item.fullPath);
      }
    },

    // 处理拖拽选择的目录或文件
    handleDropDirOrFile(item, path) {
      if (item.isDirectory) {
        const reader = item.createReader();
        reader.readEntries((entries) => {
          entries.forEach((entry) => {
            this.handleDropDirOrFile(entry, entry.fullPath);
          });
        });
      } else if (item.isFile) {
        // 转换成文件对象
        item.file(
          (file) => {
            this.localStorageFIle(file, this.getFolderPath + path);
          },
          (error) => {
            this.uploadFormDatas = [];
            this.$message.error("选择的文件错误:" + error);
          }
        );
      } else {
        this.$message.error("选择的目录或文件错误");
      }
    },

    // 点击上传目录
    uploadFolderChange(event) {
      const files = event.target.files;
      // 这里可以处理选中的文件或目录，例如展示目录结构等
      console.log(files);
      if (!files || files.length <= 0) {
        this.$message.error("请选择要上传的目录或文件");
        return;
      }
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const webkitRelativePath = files[i].webkitRelativePath;
        const realFilePath = webkitRelativePath.substring(
          webkitRelativePath.indexOf("/"),
          webkitRelativePath.length
        );
        const path = this.getFolderPath + realFilePath;
        this.localStorageFIle(file, path);
      }
    },

    // 本地缓存
    localStorageFIle(file, path) {
      const dirPath = path.substring(0, path.lastIndexOf("/"));
      this.uploadFormDatas.push({
        file: file,
        filePath: path,
        dirPath: dirPath,
        size: file.size,
        name: file.name,
        upload: 0,
        percentage: 0,
        errorMsg: null,
      });
    },

    // 确认上传文件目录信息
    handleConfirm() {
      console.log("uploadFile", this.uploadFormDatas);
      if (!this.dialogVisible) return;
      if (!this.uploadFormDatas || this.uploadFormDatas.length <= 0) {
        this.$message.error("请选择目录或文件");
        return;
      }
      this.$confirm("确定上传选择的目录吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          this.loading = true;
          let uploadIndex = 0;
          try {
            for (let i = 0; i < this.uploadFormDatas.length; i++) {
              uploadIndex = i;
              const item = this.uploadFormDatas[i];
              this.currentUploadFile = this.uploadFormDatas[i];
              const formData = new FormData();
              formData.append("file", item.file);
              formData.append("filePath", item.filePath);
              formData.append("dirPath", item.dirPath);
              const { code, message } = await uploadDir(formData, (e) => {
                let progress = Math.round((e.loaded * 100) / e.total);
                // 更新进度条或者显示进度信息
                if (progress >= 100) {
                  progress = 100;
                  item.upload = 1;
                  this.currentUploadFile.upload = 1;
                }
                item.percentage = progress;
              });
              if (code !== 200) {
                this.$set(this.uploadFormDatas[i], "upload", 3);
                this.$set(this.uploadFormDatas[i], "errorMsg", message);
                this.currentUploadFile.upload = 3;
                this.currentUploadFile.errorMsg = message;
                break;
              } else {
                this.$set(this.uploadFormDatas[i], "upload", 2);
                this.currentUploadFile.upload = 2;
              }
            }
            this.loading = false;
          } catch (e) {
            this.loading = false;
            this.$set(this.uploadFormDatas[uploadIndex], "upload", 3);
            this.$set(this.uploadFormDatas[uploadIndex], "errorMsg", e);
            this.currentUploadFile.upload = 3;
            this.currentUploadFile.errorMsg = e;
          }
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消操作",
          });
        });
    },

    // 查看文件上传详情
    uploadFileDetail() {
      this.uploadDetailConfig.visible = true;
    },

    // 上传文件详情关闭
    handleDetailClose() {
      this.uploadDetailConfig.visible = false;
    },

    // 关闭
    handleClose() {
      this.uploadFormDatas = [];
      this.currentUploadFile = {};
      this.$emit("success");
      this.$emit("update:visible", false);
    },
  },
};
</script>
<style lang="scss" scoped>
.upload-web-container {
  width: 100%;
  overflow: hidden;

  .folder-path {
    font-size: 20px;
    font-weight: bold;
    margin-left: 10%;

    .el-link {
      margin-left: 10px;
      font-size: 20px;
      font-weight: bold;
      color: #409eff;
    }
  }

  .upload-reminder {
    font-size: 15px;
    margin-left: 10%;
    margin-top: 10px;

    span:nth-child(1) {
      color: #409eff;
    }

    span:nth-child(2) {
      color: #f56c6c;
    }
  }

  .folder-upload {
    margin-top: 30px;
    margin-left: 10%;

    .upload-title {
      margin-bottom: 10px;
      font-weight: bold;
    }

    .upload-container {
      border: 1px dashed #d9d9d9;
      width: 90%;
      height: 250px;
      text-align: center;
      padding-top: 40px;

      .upload-remark > span:last-child {
        color: #409eff;
        font-style: normal;
      }
    }

    .upload-container-hover {
      border: 4px dashed #409eff;
      background-color: rgba(64, 158, 255, 0.1);
    }

    .upload-container:hover {
      border: 4px dashed #409eff;
      cursor: pointer;
      background-color: rgba(64, 158, 255, 0.1);
    }
  }

  .file-title-container {
    font-size: 20px;
    font-weight: bold;
    margin-left: 10%;
    margin-top: 20px;

    span:nth-child(2) {
      margin-left: 5px;
      color: #f56c6c;
      margin-right: 5px;
    }

    span:nth-child(4) {
      margin-left: 15px;
      margin-right: 5px;
    }

    span:nth-child(5) {
      color: #67c23a;
    }

    span:nth-child(6) {
      margin-left: 15px;

      .el-link {
        color: #409eff;
      }
    }
  }

  .current-upload-container {
    font-size: 17px;
    font-weight: bold;
    margin-left: 10%;
    margin-top: 20px;

    div {
      float: left;
      white-space: nowrap; /* 确保文本在一行内显示 */
      overflow: hidden; /* 超出容器部分隐藏 */
      text-overflow: ellipsis; /* 使用省略号表示被截断的文本 */
      width: 80px;
    }

    div:nth-child(2) {
      width: 215px;
      font-weight: normal;
      font-size: 15px;
      line-height: 25px;
    }

    div:nth-child(3) {
      width: 155px;
      margin-left: 20px;
    }
  }
}

.drawer-detail-title {
  margin-bottom: 15px;

  div {
    float: left;
    white-space: nowrap; /* 确保文本在一行内显示 */
    overflow: hidden; /* 超出容器部分隐藏 */
    text-overflow: ellipsis; /* 使用省略号表示被截断的文本 */
    width: 80px;
  }

  div:nth-child(1) {
    font-weight: bold;
    font-size: 20px;
    width: 150px;
  }

  div:nth-child(2) {
    margin-left: 30%;
  }

  div:nth-child(4) {
    margin-left: 20px;
    width: 100px;
  }

  div:nth-child(5) {
    margin-left: 20px;
    width: 150px;
  }
}

.drawer-detail-container {
  margin-left: 7%;
  width: 80%;

  .column-header {
    width: 100%;

    span {
      margin-left: 20px;
      margin-right: 20px;
    }

    span:nth-child(1) {
      margin-right: 50px;
    }

    span:nth-child(3) {
      margin-left: 70px;
      margin-right: 200px;
    }

    span:nth-child(4) {
      margin-right: 120px;
    }
  }

  .column-cell {
    width: 100%;
    margin-top: 20px;
    overflow: hidden;

    div {
      float: left;
      margin-left: 20px;
      white-space: nowrap; /* 确保文本在一行内显示 */
      overflow: hidden; /* 超出容器部分隐藏 */
      text-overflow: ellipsis; /* 使用省略号表示被截断的文本 */
      width: 100px;
    }

    div:nth-child(3) {
      width: 270px !important;
    }

    div:nth-child(4) {
      margin-left: 10px !important;
      width: 140px !important;
    }

    div:nth-child(5) {
      margin-left: 40px !important;
    }

    .upload-runing-svg-rotate {
      animation: uploadRuningSvgRotate 2s linear infinite;
      color: #67c23a;
    }

    @keyframes uploadRuningSvgRotate {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }
  }
}
</style>
